home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / editors / mjovesrc.zoo / util.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  17KB  |  1,045 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "ctype.h"
  10. #include "termcap.h"
  11. #include "disp.h"
  12. #include "fp.h"
  13. #include <signal.h>
  14. #include <errno.h>
  15. #define HAVE_STRERROR 1
  16.  
  17. #ifdef    MAC
  18. # include "mac.h"
  19. #else
  20. # ifdef    STDARGS
  21. #  include <stdarg.h>
  22. # else
  23. #  include <varargs.h>
  24. # endif
  25. #endif
  26.  
  27. #ifdef    MSDOS
  28. #include <time.h>
  29. #endif
  30.  
  31. const struct cmd *
  32. FindCmd(proc)
  33. register void    (*proc) proto((void));
  34. {
  35.     register const struct cmd    *cp;
  36.  
  37.     for (cp = commands; cp->Name; cp++)
  38.         if (cp->c_proc == proc)
  39.             return cp;
  40.     return NULL;
  41. }
  42.  
  43. bool    Interactive = NO;    /* True when we invoke with the command handler? */
  44. data_obj    *LastCmd;
  45. char    *ProcFmt = ": %f ";
  46.  
  47. void
  48. ExecCmd(cp)
  49. register data_obj    *cp;
  50. {
  51.     LastCmd = cp;
  52.     if (cp->Type & MAJOR_MODE) {
  53.         SetMajor((cp->Type >> 8));
  54.     } else if (cp->Type & MINOR_MODE) {
  55.         TogMinor((cp->Type >> 8));
  56.     } else    switch (cp->Type&TYPEMASK) {
  57.         case MACRO:
  58.             do_macro((struct macro *) cp);
  59.             break;
  60.  
  61.         case FUNCTION:
  62.             {
  63.             register struct cmd    *cmd = (struct cmd *) cp;
  64.  
  65.             if (cmd->c_proc) {
  66.                 if ((cmd->Type & MODIFIER) &&
  67.                     (BufMinorMode(curbuf, ReadOnly))) {
  68.                     rbell();
  69.                     message("[Buffer is read-only]");
  70.                 } else
  71.                     (*cmd->c_proc)();
  72.             }
  73.             }
  74.     }
  75. }
  76.  
  77. Line *
  78. lastline(lp)
  79. register Line    *lp;
  80. {
  81.     register Line    *next;
  82.  
  83.     while ((next = lp->l_next) != NULL)
  84.         lp = next;
  85.     return lp;
  86. }
  87.  
  88. char    key_strokes[100],
  89.     *keys_p = key_strokes;
  90.  
  91. void
  92. pp_key_strokes(buffer, size)
  93. char    *buffer;
  94. size_t    size;
  95. {
  96.     char    *buf_end = buffer + size - 1,
  97.         *kp = key_strokes,
  98.         c;
  99.  
  100.     *buffer = '\0';
  101.     while ((c = *kp++) != '\0') {
  102.         swritef(buffer, (size_t) (buf_end-buffer), "%p ", c);
  103.         buffer += strlen(buffer);
  104.         if (buffer >= buf_end)
  105.             break;
  106.     }
  107. }
  108.  
  109. private int    *slowp = NULL;    /* for waitchar() */
  110.  
  111. private SIGRESULT
  112. slowpoke(junk)
  113. int    junk;
  114. {
  115.     int save_errno = errno;    /* Subtle, but necessary! */
  116.     char    buffer[100];
  117.  
  118.     if (slowp)
  119.         *slowp = YES;
  120.     pp_key_strokes(buffer, sizeof (buffer));
  121.     f_mess(buffer);
  122.     errno = save_errno;
  123.     SIGRETURN;
  124. }
  125.  
  126. #ifdef    UNIX
  127. # ifdef    BSD4_2
  128. #  define N_SEC    1    /* will be precisely 1 second on 4.2 */
  129. # else
  130. #  define N_SEC    2    /* but from 1 to 2 seconds otherwise */
  131. # endif
  132. #else    /* !UNIX */
  133. # define N_SEC    1
  134. int in_macro();
  135. #endif    /* !UNIX */
  136.  
  137. int
  138. waitchar(slow)
  139. int    *slow;
  140. {
  141.     int    c;
  142. #ifdef    UNIX
  143.     unsigned int    old_time;
  144.     SIGRESULT    (*oldproc) proto((int));
  145. #else    /* !UNIX */
  146.     long sw, time();
  147. #endif    /* !UNIX */
  148.  
  149.     slowp = slow;
  150.  
  151.     if (in_macro())        /* make macros faster ... */
  152.         return getch();
  153.  
  154.     /* If slow is a valid pointer and it's value is yes, then
  155.        we know we have already been slow during this sequence,
  156.        so we just wait for the character and then echo it. */
  157.     if (slow != NULL && *slow == YES) {
  158.         c = getch();
  159.         slowpoke(0);
  160.         return c;
  161.     }
  162. #ifdef    UNIX
  163.     oldproc = signal(SIGALRM, slowpoke);
  164.  
  165.     if ((old_time = alarm((unsigned) N_SEC)) == 0)
  166.         old_time = UpdFreq;
  167.     c = getch();
  168.     (void) alarm(old_time);
  169.     (void) signal(SIGALRM, oldproc);
  170.  
  171.     if (slow != NULL && *slow == YES)
  172.         slowpoke(0);
  173.     return c;
  174.  
  175. #else    /* !UNIX */
  176. #ifdef    MAC
  177.     Keyonly = YES;
  178.     if (charp() || in_macro()) {
  179.         c = getch();    /* to avoid flicker */
  180.         if (slow != NULL && *slow == YES)
  181.             slowpoke();
  182.         return c;
  183.     }
  184. #endif
  185.     time(&sw);
  186.     sw += N_SEC;
  187.     while (time(NULL) <= sw)
  188.         if (charp() || in_macro())
  189.             return getch();
  190. #ifdef    MAC
  191.     menus_off();
  192. #endif
  193.     slowpoke();
  194.     c = getch();
  195.     slowpoke();
  196.  
  197.     return c;
  198. #endif    /* !UNIX */
  199. }
  200.  
  201. char *
  202. StrIndex(dir, buf, charpos, what)
  203. int    dir;    /* FORWARD or BACKWARD */
  204. register char    *buf;
  205. int    charpos;
  206. register int    what;
  207. {
  208.     register char    *cp = &buf[charpos];
  209.     register int    c;
  210.  
  211.     if (dir > 0) {
  212.         while ((c = *cp++) != '\0')
  213.             if ((c == what) != '\0')
  214.                 return (cp - 1);
  215.     } else {
  216.         while (cp >= buf && (c = *cp--)!='\0')
  217.             if (c == what)
  218.                 return (cp + 1);
  219.     }
  220.     return NULL;
  221. }
  222.  
  223. bool
  224. blnkp(buf)
  225. register char    *buf;
  226. {
  227.     register char    c;
  228.  
  229.     do ; while ((c = *buf++)!='\0' && (c == ' ' || c == '\t'));
  230.     return c == 0;    /* It's zero if we got to the end of the Line */
  231. }
  232.  
  233. bool
  234. within_indent()
  235. {
  236.     register char    c;
  237.     register int    i;
  238.  
  239.     i = curchar;
  240.     do ; while (--i >= 0 && ((c = linebuf[i]) == ' ' || c == '\t'));
  241.     return i < 0;        /* it's < 0 if we got to the beginning */
  242. }
  243.  
  244. Line *
  245. next_line(line, num)
  246. register Line    *line;
  247. register int    num;
  248. {
  249.     if (num < 0)
  250.         return prev_line(line, -num);
  251.     if (line)
  252.         while (--num >= 0 && line->l_next != NULL)
  253.             line = line->l_next;
  254.     return line;
  255. }
  256.  
  257. Line *
  258. prev_line(line, num)
  259. register Line    *line;
  260. register int    num;
  261. {
  262.     if (num < 0)
  263.         return next_line(line, -num);
  264.     if (line)
  265.         while (--num >= 0 && line->l_prev != NULL)
  266.             line = line->l_prev;
  267.     return line;
  268. }
  269.  
  270. void
  271. DotTo(line, col)
  272. Line    *line;
  273. int    col;
  274. {
  275.     Bufpos    bp;
  276.  
  277.     bp.p_line = line;
  278.     bp.p_char = col;
  279.     SetDot(&bp);
  280. }
  281.  
  282. /* If bp->p_line is != current line, then save current line.  Then set dot
  283.    to bp->p_line, and if they weren't equal get that line into linebuf.  */
  284.  
  285. void
  286. SetDot(bp)
  287. register Bufpos    *bp;
  288. {
  289.     register int    notequal;
  290.  
  291.     if (bp == NULL)
  292.         return;
  293.  
  294.     notequal = bp->p_line != curline;
  295.     if (notequal)
  296.         lsave();
  297.     if (bp->p_line)
  298.         curline = bp->p_line;
  299.     if (notequal)
  300.         getDOT();
  301.     curchar = bp->p_char;
  302.     if (curchar > length(curline))
  303.         curchar = length(curline);
  304. }
  305.  
  306. void
  307. ToLast()
  308. {
  309.     SetLine(curbuf->b_last);
  310.     Eol();
  311. }
  312.  
  313. int    MarkThresh = 22;    /* average screen size ... */
  314. static int    line_diff;
  315.  
  316. int
  317. LineDist(nextp, endp)
  318. register Line    *nextp,
  319.         *endp;
  320. {
  321.     (void) inorder(nextp, 0, endp, 0);
  322.     return line_diff;
  323. }
  324.  
  325. int
  326. inorder(nextp, char1, endp, char2)
  327. register Line    *nextp,
  328.         *endp;
  329. int    char1,
  330.     char2;
  331. {
  332.     register Line    *prevp = nextp;
  333.  
  334.     line_diff = 0;
  335.     if (nextp == endp)
  336.         return char1 < char2;
  337.  
  338.     while (nextp && prevp) {
  339.         nextp = nextp->l_next;
  340.         prevp = prevp->l_prev;
  341.         line_diff += 1;
  342.         if (nextp == endp)
  343.             return TRUE;
  344.         if (prevp == endp)
  345.             return FALSE;
  346.     }
  347.     while (nextp!=NULL && nextp!=endp) {
  348.         nextp = nextp->l_next;
  349.         line_diff += 1;
  350.     }
  351.     while (prevp!=NULL && prevp!=endp) {
  352.         prevp = prevp->l_prev;
  353.         line_diff += 1;
  354.     }
  355.     /* nextp == prevp implies both are NULL: the lines are not ordered */
  356.     return nextp==prevp? -1 : nextp==endp;
  357. }
  358.  
  359. void
  360. PushPntp(line)
  361. register Line    *line;
  362. {
  363.     if (LineDist(curline, line) >= MarkThresh)
  364.         set_mark();
  365. }
  366.  
  367. void
  368. ToFirst()
  369. {
  370.     SetLine(curbuf->b_first);
  371. }
  372.  
  373. int
  374. length(line)
  375. Line    *line;
  376. {
  377.     return strlen(lcontents(line));
  378. }
  379.  
  380. void
  381. to_word(dir)
  382. register int    dir;
  383. {
  384.     register char    c;
  385.  
  386.     if (dir == FORWARD) {
  387.         while ((c = linebuf[curchar]) != '\0' && !jisword(c))
  388.             curchar += 1;
  389.         if (eolp()) {
  390.             if (curline->l_next == NULL)
  391.                 return;
  392.             SetLine(curline->l_next);
  393.             to_word(dir);
  394.             return;
  395.         }
  396.     } else {
  397.         while (!bolp() && (c = linebuf[curchar - 1], !jisword(c)))
  398.             curchar -= 1;
  399.         if (bolp()) {
  400.             if (curline->l_prev == NULL)
  401.                 return;
  402.             SetLine(curline->l_prev);
  403.             Eol();
  404.             to_word(dir);
  405.         }
  406.     }
  407. }
  408.  
  409. /* Are there any modified buffers?  Allp means include B_PROCESS
  410.    buffers in the check. */
  411.  
  412. bool
  413. ModBufs(allp)
  414. bool    allp;
  415. {
  416.     register Buffer    *b;
  417.  
  418.     for (b = world; b != NULL; b = b->b_next)
  419.         if (b->b_type != B_SCRATCH
  420.         && (b->b_type == B_FILE || allp)
  421.         && IsModified(b))
  422.             return YES;
  423.     return NO;
  424. }
  425.  
  426. char *
  427. filename(b)
  428. register Buffer    *b;
  429. {
  430.     return b->b_fname ? pr_name(b->b_fname, YES) : "[No file]";
  431. }
  432.  
  433. char *
  434. itoa(num)
  435. register int    num;
  436. {
  437.     static char    line[15];
  438.  
  439.     swritef(line, sizeof(line), "%d", num);
  440.     return line;
  441. }
  442.  
  443. int
  444. min(a, b)
  445. register int    a,
  446.         b;
  447. {
  448.     return (a < b) ? a : b;
  449. }
  450.  
  451. int
  452. max(a, b)
  453. register int    a,
  454.         b;
  455. {
  456.     return (a > b) ? a : b;
  457. }
  458.  
  459. void
  460. tiewind(w, bp)
  461. register Window    *w;
  462. register Buffer    *bp;
  463. {
  464.     int    not_tied = (w->w_bufp != bp);
  465.  
  466.     UpdModLine = YES;    /* kludge ... but speeds things up considerably */
  467.     w->w_line = bp->b_dot;
  468.     w->w_char = bp->b_char;
  469.     w->w_bufp = bp;
  470.     if (not_tied)
  471.         CalcWind(w);    /* ah, this has been missing since the
  472.                    beginning of time! */
  473. }
  474.  
  475. char *
  476. lcontents(line)
  477. regi